import store from "@/store"
import { userActionType } from "@/store/modules/user"
import { handleUrlParams, showModal } from "@/utils/index"
import { getWebsocketUrl } from "@/utils/settings"
import dateUtils from "@/utils/dateUtils"

export default {
  debug: false, //开启调试模式，控制台打印日志
  socketTask: null,
  // 初始化websocket
  initializing: false, //是否正在初始化，防止多次初始化
  initPromiseList: [], //初始化的promise队列，防止多次初始化
  afterInitEventList: [], //初始化完毕后执行的事件
  heartbeatTimer: null, // 心跳定时器
  reConnectTimer: null, // 重连定时器
  pageTrackEvent: null, //页面追踪的事件
  maxConnectCount: 10, //最大尝试重连次数
  init() {
    return new Promise(async (resolve, reject) => {
      try {
        if (this.maxConnectCount <= 0) {
          console.log("达到最大尝试重连次数")
          // 5分钟后重置最大尝试重连次数，重新连接
          if (this.reConnectTimer) {
            clearTimeout(this.reConnectTimer)
          }
          this.reConnectTimer = setTimeout(() => {
            this.maxConnectCount = 10
            this.init()
          }, 300000)
          resolve()
          return
        }
        // 如果正在初始化，将promise放入队列
        if (this.initializing) {
          this.initPromiseList.push({ resolve, reject })
          return
        }
        this.initializing = true
        this.maxConnectCount--
        try {
          await this.connect()
        } catch (err) {
          console.log(dateUtils.formatDate(new Date()), err, "连接websocket失败")
        }
        let that = this
        // 监听连接打开
        this.socketTask.onOpen(async (obj) => {
          that.initializing = false
          that.reConnectTimer && clearTimeout(that.reConnectTimer)
          that.debug && console.log(dateUtils.formatDate(new Date()), obj, "成功连接 websocket 服务器")
          that.maxConnectCount = 10
          if (that.heartbeatTimer) {
            clearInterval(that.heartbeatTimer)
          }
          //重新发送页面跟踪开始信号
          if (that.pageTrackEvent) {
            await that.send.apply(that, [{ ...that.pageTrackEvent, eventType: 1 }, true])
            that.debug && console.log(dateUtils.formatDate(new Date()), { ...that.pageTrackEvent, eventType: 1 }, "发送页面跟踪开始信号")
          }
          //每隔10s发送一次心跳
          that.heartbeatTimer = setInterval(() => {
            //发送页面追踪的消息
            if (that.pageTrackEvent) {
              that.debug && console.log(dateUtils.formatDate(new Date()), that.pageTrackEvent, "周期性发送页面跟踪")
              that.send.apply(that, [that.pageTrackEvent, true])
              //发送心跳包
            } else {
              that.debug && console.log("发送心跳包")
              that.send({
                content: "心跳",
                contentType: 1,
                messageType: 0,
              })
            }
          }, 10000)
          // 执行队列中的promise
          for (let initPromiseListElement of that.initPromiseList) {
            initPromiseListElement.resolve()
          }
          that.initPromiseList = []
          // 执行队列中的事件
          for (let afterInitEventListElement of that.afterInitEventList) {
            try {
              // promise 事件
              if (afterInitEventListElement.resolve) {
                await afterInitEventListElement.event.apply(that, [afterInitEventListElement.params])
                afterInitEventListElement.resolve()
                // 普通事件
              } else {
                afterInitEventListElement.event.apply(that, [afterInitEventListElement.params])
              }
            } catch (e) {
              afterInitEventListElement.reject()
            }
          }
          that.afterInitEventList = []
          resolve()
        })
        //监听连接超时，当连接超时时再次尝试重新发起连接
        if (this.reConnectTimer) {
          clearTimeout(this.reConnectTimer)
        }
        this.reConnectTimer = setTimeout(() => {
          if (this.initializing) {
            console.log(dateUtils.formatDate(new Date()), "连接超时")
            this.initializing = false
            //关闭之前的连接
            this.socketTask.onClose(() => {})
            this.socketTask.close()
            this.initPromiseList.push({ resolve, reject })
            //重新连接
            this.init()
          }
        }, 5000)
        // 监听websocket关闭
        this.socketTask.onClose(async (obj) => {
          console.log(dateUtils.formatDate(new Date()), JSON.stringify(obj), "websocket关闭")
          that.reConnectTimer && clearTimeout(that.reConnectTimer)
          //重新连接
          await that.init()
        })
        // 监听websocket错误
        this.socketTask.onError(async (obj) => {
          console.log(dateUtils.formatDate(new Date()), JSON.stringify(obj), "websocket错误")
        })
        //监听接收到服务器传来的消息
        this.socketTask.onMessage((obj) => {
          const data = JSON.parse(obj.data)
          that.debug && console.log(dateUtils.formatDate(new Date()), data, "接收到服务器传来的消息")
          //给用户发送消息
          if (data.messageType === 2) {
            showModal({
              title: "提示",
              content: data.content,
              showCancel: false,
            })
          }
        })
      } catch (e) {
        console.log(dateUtils.formatDate(new Date()), e, "err")
      }
    })
  },
  //连接 websocket
  connect() {
    return new Promise(async (resolve, reject) => {
      const userInfo = await store.dispatch(userActionType.action.userInfo)
      this.socketTask = uni.connectSocket({
        url: handleUrlParams(getWebsocketUrl(), {
          "k-Authorization": userInfo.token,
        }),
        success: (res) => {
          resolve(res)
        },
        fail: (err) => {
          console.log(dateUtils.formatDate(new Date()), err, "连接 websocket 服务器失败")
          reject(err)
        },
      })
    })
  },
  //发送消息，reTry 是否在发送失败时尝试再次发送
  send(obj, reTry = false) {
    return new Promise(async (resolve, reject) => {
      if (!this.socketTask) {
        await this.init()
      }
      //正在初始化，等待初始化完成
      if (this.initializing) {
        // 添加后置事件，等下次连接成功时一次性发送
        if (reTry) {
          //防止重复添加
          if (this.afterInitEventList.findIndex((item) => item.event === this.send && item.params === obj) === -1) {
            this.afterInitEventList.push({ event: this.send, params: obj, resolve, reject })
          }
        } else {
          resolve()
        }
        return
      }
      let that = this
      this.socketTask.send({
        data: JSON.stringify(obj),
        success: () => {
          resolve()
        },
        fail: async (err) => {
          console.log(dateUtils.formatDate(new Date()), JSON.stringify(err), "发送websocket消息失败")
          // 添加后置事件，等下次连接成功时一次性发送
          if (reTry) {
            //防止重复添加
            if (that.afterInitEventList.findIndex((item) => item.event === that.send && item.params === obj) === -1) {
              that.afterInitEventList.push({ event: that.send, params: obj, resolve, reject })
            }
          }
          //重新连接
          // that.socketTask.close()
          // await that.init()
        },
      })
    })
  },
  //向服务器通信，跟踪当前用户所处的页面
  // eventType 1:进入页面，2:离开页面，3:处在页面中，周期性发送
  async trackCurrentPage(pageName, checkType = "", eventType = "") {
    const params = {
      content: pageName,
      contentType: 1,
      messageType: 1,
      checkType: checkType,
      eventType: eventType,
    }
    // 进入页面，记录当前页面追踪事件，等待下次心跳包周期时发送
    if (eventType === 1) {
      this.pageTrackEvent = { ...params, eventType: 3 }
    } else {
      this.pageTrackEvent = null
    }
    try {
      this.debug && console.log(dateUtils.formatDate(new Date()), params, "发送页面追踪")
      await this.send(params, true)
    } catch (e) {
      console.log(dateUtils.formatDate(new Date()), e, "error")
    }
  },
}
